/******************************************************************************
* 文件名称: list.h
* 创建者の: 孔佳伟
* 个人主页: https://gitee.com/thin-wind/jump
* 修改记录: 
******************************************************************************/

#ifndef __LIST_H_
#define __LIST_H_

#include "portmacro.h"


// 链表节点数据结构定义
typedef struct xLIST_ITEM
{
    TickType_t          xItemValue;     // 辅助值，用于帮助节点做顺序排列
    struct xLIST_ITEM*  pxNext;         // 指向链表下一个节点
    struct xLIST_ITEM*  pxPrevious;     // 指向链表前一个节点
    void*               pvOwner;        // 指向拥有该节点的内核对象，通常是 TCB
    void*               pvContainer;    // 指向该节点所在的链表
} ListItem_t;

// 链表精简节点数据结构定义
typedef struct xMINI_LIST_ITEM
{
    TickType_t          xItemValue;     // 辅助值，用于帮助节点做升序排列
    struct xLIST_ITEM*  pxNext;         // 指向链表下一个节点
    struct xLIST_ITEM*  pxPrevious;     // 指向链表前一个节点
} MiniListItem_t;

// 链表根节点数据结构定义
typedef struct xLIST
{
    UBaseType_t         uxNumberOfItems;// 链表节点计数器，用于表示该链表下有多少个节点
    ListItem_t*         pxIndex;        // 链表节点索引指针，用于遍历节点
    MiniListItem_t      xListEnd;       // 链表最后一个节点，环形链表，首尾相连
} List_t;


// 初始化节点的拥有者
#define listSET_LIST_ITEM_OWNER(pxListItem, pxOwner) \
        ((pxListItem)->pvOwner = (void *)(pxOwner))

// 获取节点拥有者
#define listGET_LIST_ITEM_OWNER(pxListItem) \
        ((pxListItem)->pvOwner)

// 初始化节点排序辅助值
#define listSET_LIST_ITEM_VALUE(pxListItem, xValue) \
        ((pxListItem)->xItemValue = (xValue))

// 获取节点排序辅助值
#define listGET_LIST_ITEM_VALUE(pxListItem) \
        ((pxListItem)->xItemValue)

// 获取链表根节点的节点计数器的值
#define listGET_ITEM_VALUE_OF_HEAD_ENTRY(pxList) \
        (((pxList)->xListEnd).pxNext->xItemValue)

// 获取链表的入口节点
#define listGET_HEAD_ENTRY(pxList) \
        (((pxList)->xListEnd).pxNext)

// 获取节点的下一个节点
#define listGET_NEXT(pxListItem) \
        (( pxListItem)->pxNext)

// 获取链表的最后一个节点
#define listGET_END_MARKER(pxList) \
        ((ListItem_t const *)(&((pxList)->xListEnd)))

// 判断链表是否为空
#define listLIST_IS_EMPTY(pxList) \
        ((BaseType_t)((pxList)->uxNumberOfItems == (UBaseType_t)0))

// 获取链表的节点数
#define listCURRENT_LIST_LENGTH(pxList) \
        ((pxList)->uxNumberOfItems)

// 遍历链表，每调用一次，链表的 pxIndex 变量就会指向下一个节点，并且返回这个节点的 pxOwner 变量值
#define listGET_OWNER_OF_NEXT_ENTRY(pxTCB, pxList) \
        { \
            List_t* const pxConstList = (pxList); \
            /* 节点索引指向链表第一个节点 */ \
            (pxConstList)->pxIndex = (pxConstList)->pxIndex->pxNext; \
            /* 当已经遍历到尾节点时，重新指向链表头 */ \
            if((void *)(pxConstList)->pxIndex == (void *)&((pxConstList)->xListEnd)) \
            { \
                (pxConstList)->pxIndex = (pxConstList)->pxIndex->pxNext; \
            } \
            /* 获取节点的 OWNER，即 TCB */ \
            (pxTCB) = ( pxConstList )->pxIndex->pvOwner; \
        }

// 相当于 container_of 宏已知链表节点，得到包含该链表节点对象的首地址，
// 在创建任务时，链表节点的 pvOwner 被绑定为对应任务的 TCB 块
// 所以最终我们得到的是任务 PCB 块这个数据结构的首地址
#define listGET_OWNER_OF_HEAD_ENTRY(pxList)  ((&((pxList)->xListEnd))->pxNext->pvOwner)


// 链表节点初始化
void vListInitialiseItem(ListItem_t* const pxItem);

// 链表根节点初始化
void vListInitialise(List_t* const pxList);

// 节点插入到链表的尾部
void vListInsertEnd(List_t* const pxList, ListItem_t* const pxNewListItem);

// 将节点按照升序排列插入到链表
void vListInsert(List_t* const pxList, ListItem_t* const pxNewListItem);

// 将节点从链表删除
UBaseType_t uxListRemove(ListItem_t* const pxItemToRemove);



#endif
